/*
 * Copyright (c) 2017. Visionet and/or its affiliates. All right reserved.
 * VISIONET PROPRIETARY/CONFIDENTIAL.
 */
package com.visionet.security.filter;

import java.util.List;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.visionet.security.domain.dto.UrlizedResource;
import com.visionet.security.support.ResourceHelper;
import com.visionet.security.utils.WebUtils;

/**
 * 
 *
 * @author suxiaojing
 * @date 
 * @since 0.0.1
 */
public class DynamicPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
	
	private final Logger logger = LoggerFactory.getLogger(getClass());

	private boolean permissionInherit = false;

	/**
	 * @return the permissionInherit
	 */
	public boolean isPermissionInherit() {
		return permissionInherit;
	}

	/**
	 * @param permissionInherit
	 *            the permissionInherit to set
	 */
	public void setPermissionInherit(boolean permissionInherit) {
		this.permissionInherit = permissionInherit;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.apache.shiro.web.filter.PathMatchingFilter#preHandle(javax.servlet
	 * .ServletRequest, javax.servlet.ServletResponse)
	 */
	@Override
	protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
		List<UrlizedResource> resourceList = ResourceHelper.getUrlizedResource();
		for (UrlizedResource resource : resourceList) {
			if (StringUtils.isNotEmpty(resource.getUrl()) && pathsMatch(request, resource)) {
				return isFilterChainContinued(request, response, resource.getUrl(),
						new String[] { resource.generatePermissionString() });
			}
		}
		// no path matched, allow the request to go through:
		return true;

	}

	/**
	 * @param request
	 * @param resource
	 * @return
	 */
	protected boolean pathsMatch(ServletRequest request, UrlizedResource resource) {
		String pattern = resource.getPattern(permissionInherit);
		String path;
		switch (resource.getType()) {
		case MENU:
			path = getPathWithinApplication(request);
			break;
		case PATH:
			path = WebUtils.getFullRequestURI(WebUtils.toHttp(request));
			break;
		default:
			logger.warn("No match handle for resoruce type [{}], skip", resource.getType());
			return false;
		}
		return super.pathsMatch(pattern, path);
	}

	private boolean isFilterChainContinued(ServletRequest request, ServletResponse response, String path,
			Object pathConfig) throws Exception {
		if (isEnabled(request, response, path, pathConfig)) { // isEnabled check
			// added in 1.2
			logger.trace("Filter '{}' is enabled for the current request under path '{}' with config [{}].  "
					+ "Delegating to subclass implementation for 'onPreHandle' check.", new Object[] {
					getName(), path, pathConfig });
			// The filter is enabled for this specific request, so delegate to
			// subclass implementations
			// so they can decide if the request should continue through the
			// chain or not:
			return onPreHandle(request, response, pathConfig);
		}

		logger.trace("Filter '{}' is disabled for the current request under path '{}' with config [{}].  "
				+ "The next element in the FilterChain will be called immediately.", new Object[] {
				getName(), path, pathConfig });
		// This filter is disabled for this specific request,
		// return 'true' immediately to indicate that the filter will not
		// process the request
		// and let the request/response to continue through the filter chain:
		return true;
	}

}
